JS 表單驗證


Posted by s103071049 on 2021-06-20

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>新拖延運動報名表單</title>
    <link rel="stylesheet" href="https://necolas.github.io/normalize.css/8.0.1/normalize.css"/>
    <link rel="stylesheet" href="./new.css">
</head>
<body>
    <div class="wrapper">
        <form class="apply-form">
            <h1 class="apply-form__title">新拖延運動報名表單</h1>
            <p class="apply-form__desc">
                活動日期:2020/12/10 ~ 2020/12/11<br>
                活動地點:台北市大安區新生南路二段1號
            </p>
            <p class="apply-form__notice">
                *必填
            </p>
            <div class="input-block required hide-error">
                <div class="input-block__title">
                    暱稱
                </div>
                <div class="input-block__input">
                    <input name="nickname" type="text" placeholder="您的回答" />
                </div>
                <div class="input-block__error">請輸入暱稱</div>
            </div>
            <div class="input-block required hide-error">
                <div class="input-block__title">
                    電子郵件
                </div>
                <div class="input-block__input">
                    <input name="email" type="text" placeholder="您的電子郵件" />
                </div>
                <div class="input-block__error">請輸入電子郵件</div>
            </div>
            <div class="input-block required hide-error">
                <div class="input-block__title">
                    手機號碼
                </div>
                <div class="input-block__input">
                    <input name="phone" type="text" placeholder="您的手機號碼" />
                </div>
                <div class="input-block__error">請輸入手機號碼</div>
            </div>
            <div class="input-block required hide-error">
                <div class="input-block__title">
                    報名類型
                </div>
                <div class="input-block__input">
                    <label>
                        <input name="type" value="1" type="radio"/>躺在床上用想像力實作
                    </label>
                    <label>
                        <input name="type" value="2" type="radio"/>趴在地上滑手機找現成的
                    <label>
                </div>
                <div class="input-block__error">請輸入報名類型</div>
            </div>                  
            <div class="input-block required hide-error">
                <div class="input-block__title">
                    怎麼知道這個活動的?
                </div>
                <div class="input-block__input">
                    <input name="referal" type="text" placeholder="您的回答"/>
                </div>
                <div class="input-block__error">請輸入資料</div>
            </div>                              
            <div class="input-block">
                <div class="input-block__title">
                    其它
                </div>
                <div class="input-block__desc">
                    對活動的一些建議
                </div>
                <div class="input-block__input">
                    <input name="other" type="text" placeholder="您的回答"/>
                </div>
            </div>
            <input class="apply-form__submit" type="submit"/>
            <p class="apply-form__warn">
                請勿透過表單送出您的密碼。
            </p>
        </form>
    </div>
    <footer>© 2020 © Copyright. All rights Reserved.</footer>
    <script src="./new.js"></script>

</body>
</html>
// 不要將事件加在 submit 按鈕上,因為按 enter 也可以送出表單,不是只有按 btn 才會送出
document
  .querySelector('form')
  .addEventListener('submit', function(e) {
    let hasError = false
    let values = {}
    e.preventDefault()
    const inputs = document.querySelectorAll('.required input[type=text]')
    for (let input of inputs) {
      values[input.name] = input.value

      if (!input.value) {
        // 只是控制他顯示不顯示
        input.parentNode.parentNode.classList.remove('hide-error')
        hasError = true
      } else {
        input.parentNode.parentNode.classList.add('hide-error')
      }
    }
    const elements = document.querySelectorAll('.required')
    for (element of elements) {

      const radios = element.querySelectorAll('input[type=radio]')
      if (!radios.length) continue
      let hasValue = [...radios].some(radio => radio.checked)
      if (!hasValue) {
        element.classList.remove('hide-error')
        hasError = true
      } else {
        element.classList.add('hide-error')
      }
    }
  })

重構

document
  .querySelector('form')
  .addEventListener('submit', function(e) {
    let hasError = false
    let values = {}
    e.preventDefault()
    const elements = document.querySelectorAll('.required')
    for (element of elements) {
      const input = element.querySelector('input[type=text]')

        if (input) {
        values[input.name] = input.value
        if (!input.value) {
          // 只是控制他顯示不顯示
          element.classList.remove('hide-error')
          hasError = true
        } else {
          element.classList.add('hide-error')
        }      
      } 
      const radios = element.querySelectorAll('input[type=radio]')
      if (!radios.length) continue
      let hasValue = [...radios].some(radio => radio.checked)
      if (!hasValue) {
        element.classList.remove('hide-error')
        hasError = true
      } else {
        element.classList.add('hide-error')
      }

    }
  })

邏輯:

  1. 對 form 加 submit 事件
  2. hasValue 檢視欄位是否驗證不過
  3. values 存最後結果
  4. 找 required 元素 => 那些為必填元素
  5. 再從必填元素底下,去找哪些是 radio 哪些是 input
  6. 如果他是 input 我們就將值放進去,如果他沒有值,就讓 isVaild = false,代表這個 input 是沒有輸入東西的
  7. 檢查有無 radios,如果有再檢查是否有任何一個是有打勾的,如果有打勾,我們就將值放進去,如果沒有也表示不合法
  8. 最後檢視有無通過驗證,也就是合法不合法。如果沒有過驗證,就將錯誤隱藏的 class 移除,將 hasError 設為 true => 顯示錯誤信息;反之,
  9. 如果沒有 error,就將結果印出來

做得好否,與擴充性有很強的關聯。因為我們沒有針對特定的欄位。所以可以做出很 general 的東西。


#form-validation







Related Posts

寫一個簡單堪用的 ESLint plugin

寫一個簡單堪用的 ESLint plugin

Day05: GraphQL - Types and Schema wiht node.js

Day05: GraphQL - Types and Schema wiht node.js

N3_gulp 簡介及使用

N3_gulp 簡介及使用


Comments